package org.iteam.bank.signed.service;

import java.math.BigDecimal;

import org.iteam.bank.mina.client.IoSessionConn;
import org.iteam.bank.mina.client.IoSessionFactory;
import org.iteam.bank.mina.client.ResultMessage;
import org.iteam.bank.signed.model.AccountBalance;
import org.iteam.commons.codec.AESCoder;
import org.iteam.commons.codec.HMACCoder;
import org.iteam.commons.utils.PkGenerator;
import org.iteam.mina.Constant;
import org.iteam.mina.message.BaseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class GSPService {
	private static final Logger logger = LoggerFactory.getLogger(SignedService.class);

	private IoSessionFactory factory = IoSessionFactory.getInstance();
	private String toket = PkGenerator.genUUIDD();
	private static final int rule = 0x00000000;
	private static final int ver = 0x00000001;

	private GSPService() {
		super();
	}

	public static GSPService getInstance() {
		return Subclass.service;
	}

	private static final class Subclass {
		public static final GSPService service = new GSPService();

	}

	/**
	 * 查询账户余额
	 * 
	 * @param userBankAccount
	 * @param userName
	 * @param protocolNo
	 * @return
	 */
	public AccountBalance queryBalance(String userBankAccount, String userName, String protocolNo) throws Exception {
		AccountBalance accountBalance = new AccountBalance();
		// userBankAccount = "6228671149617277";
		// userName = "蒲公英";
		// protocolNo = "100000001361";
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11810900);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("userBankAccount", userBankAccount);
		contentJson.put("userName", userName);
		contentJson.put("protocolNo", protocolNo);
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			if (res.isSuccess() && res.verify()) {
				res.decrypt();

				JSONObject jsonObject = JSON.parseObject(new String(res.getContent(), Constant.UTF_8));
				logger.debug("{},{},余额查询结果：{}", userBankAccount, userName, jsonObject.toJSONString());
				BigDecimal availableBalance = jsonObject.getBigDecimal("availableBalance");
				BigDecimal frozenBalance = jsonObject.getBigDecimal("frozenBalance");
				accountBalance.setFrozenBalance(frozenBalance);
				accountBalance.setAvailableBalance(availableBalance);
				accountBalance.setAccountBalance(availableBalance.add(frozenBalance));
			} else {
				return null;
			}

		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
		return accountBalance;
	}

	/**
	 * 绑卡验证码发送..
	 * 
	 * @param tel
	 *            电话号码
	 * @return
	 * @throws Exception
	 */
	public String sendCaptcha(String tel) throws Exception {
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11810300);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("tel", tel);
		logger.debug("绑卡验证码发送[{}]", tel);
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			if (res.isSuccess() && res.verify()) {
				res.decrypt();

				JSONObject jsonObject = JSON.parseObject(new String(res.getContent(), Constant.UTF_8));
				logger.debug("绑卡验证码发送结果:{}", jsonObject.toJSONString());
				return jsonObject.getString("serialNo");
			}
		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
		return null;
	}

	/**
	 * 获取联行号信息
	 * 
	 * <pre>
	 * totalNum		BigDecimal[4P0]	返回笔数
	 * list			JsonArray	银行列表
	 * 				bankNo	String[13A]	银行号
	 * 				bankName	String[8O]	联行名
	 * </pre>
	 * 
	 * @param bankName
	 * @return
	 * @throws Exception
	 */
	public JSONObject searchBankName(String bankName) throws Exception {
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11811200);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("bankName", bankName);
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			if (res.isSuccess() && res.verify()) {
				res.decrypt();
				JSONObject jsonObject = JSON.parseObject(new String(res.getContent(), Constant.UTF_8));
				return jsonObject;
			}
		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
		JSONObject res = new JSONObject();
		res.put("totalNum", 0);
		return res;
	}

	/**
	 * 实卡绑定
	 * 
	 * @return
	 * @throws Exception
	 */
	private ResultMessage realCardbinding(String bankCard, String idCard, String name, String p2p_user_id, String mobile, String captcha, String serialNo)
			throws Exception {
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11810400);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("account", p2p_user_id);
		contentJson.put("userName", name);
		contentJson.put("userIdCard", idCard);
		contentJson.put("userBankAccount", bankCard);
		contentJson.put("tel", mobile);
		contentJson.put("serialNo", serialNo);
		contentJson.put("code", captcha);
		logger.debug("{},实卡绑定参数:{}", idCard, contentJson.toJSONString());
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			return res;
		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
	}

	/**
	 * 实卡绑定
	 * 
	 * @return
	 * @throws Exception
	 */
	private ResultMessage electronicCardbinding(String bankCard, String idCard, String name, String p2p_user_id, String mobile, String captcha,
			String serialNo, String province, String city, String bankBranch_no, String bankBranch) throws Exception {
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11810500);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("account", p2p_user_id);
		contentJson.put("userName", name);
		contentJson.put("userIdCard", idCard);
		contentJson.put("userExtBankAccount", bankCard);
		contentJson.put("tel", mobile);
		// contentJson.put("birthplace", "重庆");
		// contentJson.put("address", "重庆渝北区");
		// contentJson.put("nation", "001");
		// contentJson.put("profession", "0001");
		// contentJson.put("certAddress", "重庆渝北区");
		// contentJson.put("certValidDate", "20990101");
		// contentJson.put("certOrgRegion", "6530");
		// contentJson.put("certOrgName", "重庆市公安局");
		contentJson.put("extBankCode", bankBranch_no);
		contentJson.put("extBankName", bankBranch);
		contentJson.put("extBankProvince", province);
		contentJson.put("extBankCity", city);
		contentJson.put("serialNo", serialNo);
		contentJson.put("code", captcha);
		logger.debug("{},电子账户开立参数:{}", idCard, contentJson.toJSONString());
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			return res;
		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
	}

	/**
	 * 银行卡绑定
	 * 
	 * @param name
	 *            姓名
	 * @param bankCard
	 *            银行卡号
	 * @param bankType
	 *            银行卡类型
	 * @param idCard
	 *            身份证件号码
	 * @param mobile
	 *            银行预留手机号码
	 * @param captcha
	 *            银行预留手机号码
	 * @param serialNo
	 *            短信验证流水号
	 * @param province
	 *            省份
	 * @param city
	 *            城市
	 * @param bankBranch_no
	 *            联行号
	 * @param bankBranch
	 *            开户支行名称
	 * @param isRCB
	 *            是否是农商行卡片
	 * @param p2p_user_id
	 *            p2p用户ID
	 * @return
	 * @throws Exception
	 */
	public ResultMessage bindingCard(String name, String bankCard, String bankType, String idCard, String mobile, String captcha, String serialNo,
			String province, String city, String bankBranch_no, String bankBranch, boolean isRCB, String p2p_user_id) throws Exception {
		if (isRCB) {
			return realCardbinding(bankCard, idCard, name, p2p_user_id, mobile, captcha, serialNo);
		} else {
			return electronicCardbinding(bankCard, idCard, name, p2p_user_id, mobile, captcha, serialNo, province, city, bankBranch_no, bankBranch);
		}
	}

	/**
	 * 产品认购
	 * 
	 * @param orderNo
	 *            订单号
	 * @param productCode
	 *            产品编码
	 * @param p2p_user_id
	 *            用户id
	 * @param bankCard
	 *            银行卡号（电子帐号）
	 * @param protocolNo
	 *            协议号
	 * @param userName
	 *            用户姓名
	 * @param idCard
	 *            身份证号码
	 * @param bankProductCode
	 *            银行产品编号
	 * @param bankProductName
	 *            银行产品名称
	 * @param amount
	 *            认购金额（元，2位小数）
	 * @return <pre>
	 * 1	contractNo	String[100A]	合同编号	
	 * 2	channelSerialNo	String[15A]	渠道流水号	
	 * 3	tradeStatus	String[2A]	交易状态	见数据字典说明
	 * 4	tradeStatusMsg	String[10O]	状态描述
	 * 5	balance	BigDecimal[15P2]	产品余额
	 * </pre>
	 * @throws Exception
	 */
	public ResultMessage subscribe(String orderNo, String productCode, String p2p_user_id, String bankCard, String protocolNo, String userName, String idCard,
			String bankProductCode, String bankProductName, BigDecimal amount) throws Exception {
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11810600);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("orderNo", orderNo);
		contentJson.put("productCode", productCode);
		contentJson.put("account", p2p_user_id);
		contentJson.put("protocolNo", protocolNo);
		contentJson.put("userName", userName);
		contentJson.put("userIdCard", idCard);
		contentJson.put("userBankAccount", bankCard);
		contentJson.put("bankProductCode", bankProductCode);
		contentJson.put("bankProductName", bankProductName);
		contentJson.put("amount", amount.intValueExact() * 100);

		logger.debug("{},产品认购参数:{}", orderNo, contentJson.toJSONString());
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			return res;
		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
	}

	/**
	 * 认购状态查询
	 * 
	 * @param orderNo
	 * @return
	 * @throws Exception
	 */
	public ResultMessage subscribeStatusQuery(String orderNo) throws Exception {
		BaseMessage req = new BaseMessage();
		// req.setLength(length);
		req.setCmd(0x11810700);
		req.setRule(rule);
		req.setVer(ver);
		req.setSeq(PkGenerator.genUUIDD());
		req.setToken(toket);
		JSONObject contentJson = new JSONObject();
		contentJson.put("orderNo", orderNo);
		logger.debug("{},产品认购状态查询参数:{}", orderNo, contentJson.toJSONString());
		IoSessionConn sessionConn = null;
		try {
			byte[] contentByte = contentJson.toJSONString().getBytes(Constant.UTF_8);
			req.setContent(AESCoder.encrypt(contentByte, IoSessionFactory.KEY_AES));
			req.setVerify(HMACCoder.encryptHMAC(req.getContent(), IoSessionFactory.KEY_HMAC));
			sessionConn = factory.getSession();
			sessionConn.write(req, true);
			ResultMessage res = new ResultMessage(sessionConn.read(true));
			return res;
		} catch (Exception e) {
			throw e;
		} finally {
			factory.releaseSession(sessionConn);
		}
	}

}
